package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.ConfigConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.pojo.vo.FormDataRepeatBatchVO;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaySheetTypeEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.ProUpdateHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.pojo.AddMuchFieldPojo;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.pojo.AttrValuePojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.dto.AddBatchDTO;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataDeleteBatchDTO;
import com.xbongbong.paas.pojo.dto.FormDataUpdateGetDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.StartProcessDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.pojo.vo.StartProcessVO;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.service.team.TeamDataHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.businessrule.pojo.dto.OperationDTO;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.InvoiceErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.PayErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.PaymentErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TemplateErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.UserTeamErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.dto.FormDataRepeatBatchDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.message.constant.PayPlanPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.payment.pojo.vo.PaymentInsertBatchVO;
import com.xbongbong.pro.payment.pojo.vo.PaymentUpdateBatchMuchFieldVO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanBadReturnDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanDeleteBatchDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanEditAttrUpdateDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanInsertBatchDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanUpdateBatchDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanUpdateBatchMuchFieldDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanUpdateDTO;
import com.xbongbong.pro.payplan.pojo.vo.PayPlanDeleteBatchVO;
import com.xbongbong.pro.payplan.pojo.vo.PayPlanUpdateBatchVO;
import com.xbongbong.pro.payplan.pojo.vo.PayPlanVO;
import com.xbongbong.pro.payplansheet.pojo.dto.PayPlanSheetInsertBatchDTO;
import com.xbongbong.pro.payplansheet.pojo.dto.PayPlanSheetInsertDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.pro.service.toolbox.statistic.help.FormHelp;
import com.xbongbong.pro.sheet.pojo.dto.SheetDeleteHandleRelateDTO;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.process.operate.ProcessStartHelp;
import com.xbongbong.saas.analytical.impl.PayPlanValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.FundAccountEntity;
import com.xbongbong.saas.domain.entity.PayPlanUserEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.PayPlanEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.SupplierEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.PayPlanEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PaymentEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInvoiceEnum;
import com.xbongbong.saas.enums.business.SupplierEnum;
import com.xbongbong.saas.enums.dictionary.HasRedEnum;
import com.xbongbong.saas.enums.dictionary.PayPlanStatusEnum;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaasDeleteHelp;
import com.xbongbong.saas.help.SaasPayPlanHelper;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.help.fund.PayPlanHelp;
import com.xbongbong.saas.model.FundAccountModel;
import com.xbongbong.saas.model.PayPlanModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PayPlanUserModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.SupplierModel;
import com.xbongbong.saas.service.PayPlanService;
import com.xbongbong.saas.service.PayPlanSheetService;
import com.xbongbong.saas.service.PurchaseInvoiceService;
import com.xbongbong.saas.service.PurchaseService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.toolbox.help.FundMoneyHelp;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;


/**
 * 付款计划业务实现
 *
 * @author feng.zheng
 * @version v1.0
 * @date 2019/1/22 15:10
 * @since v1.0
 */
@Service("payPlanService")
public class PayPlanServiceImpl implements PayPlanService {

    private static final Logger LOG = LoggerFactory.getLogger(PayPlanServiceImpl.class);

    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private PayPlanModel payPlanModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasFormDataService paasFormDataService;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private PayPlanSheetService payPlanSheetService;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PayPlanSheetModel payPlanSheetModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private ProcessStartHelp processStartHelp;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private UserModel userModel;
    @Resource
    private PayPlanUserModel payPlanUserModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private SaasDeleteHelp saasDeleteHelp;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private PurchaseInvoiceService purchaseInvoiceService;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private SupplierModel supplierModel;
    @Resource
    private FundMoneyHelp fundMoneyHelp;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    private FormHelp formHelp;
    @Resource
    private PurchaseService purchaseService;
    @Resource
    private PayPlanHelp payPlanHelp;
    @Resource
    private FundAccountModel fundAccountModel;
    @Resource
    private ProUpdateHelp proUpdateHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private PayPlanValidateAnalyticalServiceImpl payPlanAnalyticalService;
    @Resource
    private SaasPayPlanHelper saasPayPlanHelper;
    @Resource
    private TeamDataHelp teamDataHelp;
    @Resource
    private UserTeamHelp userTeamHelp;

    /**
     * 付款计划保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @throws XbbException 业务异常
     * @author feng.zheng
     * @date 2019/1/18
     */
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
       payPlanAnalyticalService.beforeSave(validateDataDTO);
    }

    /**
     * 付款计划保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 业务异常
     * @author feng.zheng
     */
    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        // 团队保存
        teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), saasFormSaveDTO.getNewPaasFormDataEntity().getId(), saasFormSaveDTO.getNewPaasFormDataEntity(), saasFormSaveDTO.getIsImport(), false);
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public FormDataAddVO payPlan(PayPlanDTO payPlanDTO) throws XbbException {
        String userId = payPlanDTO.getUserId();
        String corpid = payPlanDTO.getCorpid();
        // 审批兼容
        if (payPlanDTO.getProcessCreatorId() != null) {
            userId = payPlanDTO.getProcessCreatorId();
        }
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        List<AddMuchFieldPojo> addBatchList = payPlanDTO.getAddBatchList();

        // 开启严控模式后生成流水号
        PaasFormExplainEntity formExplainEntity = paasFormExplainModel.getByFormId(payPlanDTO.getFormId(), payPlanDTO.getCorpid());
        if (Objects.isNull(formExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(formExplainEntity.getExplains(), null);
        FieldAttrEntity fieldAttrEntity = explainMap.get(PaymentEnum.PAYMENT_NO.getAttr());
        if (Objects.nonNull(fieldAttrEntity) && Objects.equals(fieldAttrEntity.getStrictController(), BasicConstant.ONE)) {
            FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
            BeanUtil.copyProperties(payPlanDTO, formDataAddDTO);
            String serialNo = "";
            for (AddMuchFieldPojo addMuchFieldPojo : addBatchList) {
                if (Objects.equals(fieldAttrEntity.getStrictController(), BasicConstant.ONE) && StringUtil.isEmpty(addMuchFieldPojo.getSerialNo())) {
                    serialNo = saasSaveHelp.getSerialNo(serialNo, formDataAddDTO, corpid, fieldAttrEntity);
                    addMuchFieldPojo.setSerialNo(serialNo);
//                    addMuchFieldPojo.getData().put(PayPlanEnum.PAY_PLAN_NO.getAttr(), serialNo);
                }
            }
        }

        List<AddMuchFieldPojo> updateBatchList = payPlanDTO.getUpdateBatchList();
        List<AddMuchFieldPojo> delBatchList = payPlanDTO.getDelBatchList();

        try {
            PaymentInsertBatchVO paymentInsertBatchVO = new PaymentInsertBatchVO();
            PaymentUpdateBatchMuchFieldVO paymentUpdateBatchMuchFieldVO = new PaymentUpdateBatchMuchFieldVO();

            // 插入数据
            if(Objects.nonNull(addBatchList) && !addBatchList.isEmpty()){
                PayPlanInsertBatchDTO payPlanInsertBatchDTO = new PayPlanInsertBatchDTO();
                BeanUtil.copyProperties(payPlanDTO, payPlanInsertBatchDTO);
                payPlanInsertBatchDTO.setDataList(addBatchList);
                paymentInsertBatchVO = insertBatch(payPlanInsertBatchDTO,payPlanDTO.getParentNew(),userId);
            }
            //更新数据
            if(Objects.nonNull(updateBatchList) && !updateBatchList.isEmpty()){
                PayPlanUpdateBatchMuchFieldDTO payPlanUpdateBatchMuchFieldDTO = new PayPlanUpdateBatchMuchFieldDTO();
                BeanUtil.copyProperties(payPlanDTO, payPlanUpdateBatchMuchFieldDTO);
                payPlanUpdateBatchMuchFieldDTO.setDataList(updateBatchList);
                paymentUpdateBatchMuchFieldVO = updateBatchMuchField(payPlanUpdateBatchMuchFieldDTO, true, explainMap);
            }
            // 删除逻辑
            if (Objects.nonNull(delBatchList) && !delBatchList.isEmpty()) {
                List<Long> idList = new ArrayList<>();
                delBatchList.forEach(item->{
                    if (Objects.nonNull(item)) {
                        idList.add(item.getId());
                    }
                });
                if (!idList.isEmpty()) {
                    PayPlanDeleteBatchDTO payPlanDeleteBatchDTO = new PayPlanDeleteBatchDTO();
                    BeanUtil.copyProperties(payPlanDTO, payPlanDeleteBatchDTO);
                    payPlanDeleteBatchDTO.setDataIdList(idList);
                    payPlanDeleteBatchDTO.setStatus(PayPlanStatusEnum.UN_RECEIVABLES.getCode());
                    PayPlanDeleteBatchVO payPlanDeleteBatchVO = deleteBatch(payPlanDeleteBatchDTO);
                    if (Objects.isNull(payPlanDeleteBatchVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                    }
                }
            }
            // 添加回款单
            addPayPlanSheet(payPlanDTO, paymentInsertBatchVO, paymentUpdateBatchMuchFieldVO);

            if (!Objects.equals(payPlanDTO.getIsImport(), 1)) {
                List<PaasFormDataEntityExt> payPlanEntityExts = paymentInsertBatchVO.getInsertList();
                if (payPlanEntityExts != null) {
                    for (PaasFormDataEntityExt paymentEntityExt : payPlanEntityExts) {
                        UserEntity userEntity = userModel.getByKeyIngoreDel(paymentEntityExt.getCreatorId(), paymentEntityExt.getCorpid());
                        Long dataId = paymentEntityExt.getId();
                        // 付款计划新建消息推送
                        if (Objects.nonNull(userEntity)) {
                            List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.PAY_PLAN_ADD.getCode(), PushTypeEnum.PAY_PLAN_ADD.getSubCode(), userEntity, paymentEntityExt);
                            PushRefTypePojo.Options options = new PushRefTypePojo.Options(paymentEntityExt.getAppId(), paymentEntityExt.getMenuId(), paymentEntityExt.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.PAY_PLAN.getCode(), XbbRefTypeEnum.PAY_PLAN.getCode());
                            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(PayPlanPushConstant.PAY_PLAN_ADD_TITLE), String.format(I18nMessageUtil.getMessage(PayPlanPushConstant.PAY_PLAN_ADD_CONTENT), userEntity.getName(), paymentEntityExt.getData().getString(PayPlanEnum.LINK_PURCHASE_LINK_TEXT.getAttr())), null, options);
                            baseProducer.sendMessage(PushTypeEnum.PAY_PLAN_ADD, messageRabbitMqDTO);
                        }
                    }
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("payPlanServiceImpl.payPlan付款出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
        return formDataAddVO;
    }

    private void addPayPlanSheet(PayPlanDTO payPlanDTO, PaymentInsertBatchVO paymentInsertBatchVO, PaymentUpdateBatchMuchFieldVO paymentUpdateBatchMuchFieldVO) throws XbbException{
        try {
            List<PayPlanSheetInsertDTO> payPlanSheetList = new ArrayList<>();
            List<Map<String, Object>> needUpdatePayPlanList = new ArrayList<>();
            List<PaasFormDataEntityExt> needAddSheetList = new ArrayList<>();
            if(Objects.nonNull(paymentInsertBatchVO) && !paymentInsertBatchVO.getPaidForList().isEmpty()) {
                needAddSheetList.addAll(paymentInsertBatchVO.getPaidForList());
            }
            if(Objects.nonNull(paymentUpdateBatchMuchFieldVO) && !paymentUpdateBatchMuchFieldVO.getPaidForList().isEmpty()) {
                List<PaasFormDataEntityExt> updateNeedAddSheetList = new ArrayList<>();
                List<AddMuchFieldPojo> paidForList = paymentUpdateBatchMuchFieldVO.getPaidForList();
                try {
                    BeanUtil.copyPropertiesList(paidForList, updateNeedAddSheetList, PaasFormDataEntityExt.class);
                } catch (Exception e) {
                }
                needAddSheetList.addAll(updateNeedAddSheetList);
            }
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode(), payPlanDTO.getCorpid());
            FundAccountEntity fundAccountEntity = fundAccountModel.getDefaultFundAccount(payPlanDTO.getCorpid());
            needAddSheetList.forEach((item)->{
                PayPlanSheetInsertDTO payPlanSheetInsertDTO = new PayPlanSheetInsertDTO();
                BeanUtil.copyProperties(item, payPlanSheetInsertDTO);
                payPlanSheetInsertDTO.setAppId(paasFormEntityExt.getAppId());
                payPlanSheetInsertDTO.setMenuId(paasFormEntityExt.getMenuId());
                payPlanSheetInsertDTO.setFormId(paasFormEntityExt.getId());
                payPlanSheetInsertDTO.setOwnerId(payPlanDTO.getUserId());
                JSONObject paymentData = item.getData();
                JSONObject data = SaasDataInitHelp.initPayPlanSheet();
                Map<String, Object> updatePayPlanMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                String serialNo = item.getSerialNo() + ".1";
                try {
                    SaasDataInitHelp.dataSet(data, PaySheetEnum.LINK_SUPPLIER.getAttr(),paymentData.getString(PayPlanEnum.LINK_SUPPLIER.getAttr()));
                    SaasDataInitHelp.dataSetNotNull(data, PaySheetEnum.PAY_PLAN_NO.getAttr(), serialNo);
                    SaasDataInitHelp.dataSet(data, PaySheetEnum.AMOUNT.getAttr(), paymentData.get(PayPlanEnum.AMOUNT.getAttr()));
                    SaasDataInitHelp.dataSet(data, PaySheetEnum.WRITE_OFF_AMOUNT.getAttr(), paymentData.get(PayPlanEnum.AMOUNT.getAttr()));
                    SaasDataInitHelp.dataSet(data, PaySheetEnum.ESTIMATE_TIME.getAttr(), paymentData.get(PayPlanEnum.ESTIMATE_TIME.getAttr()));
                    SaasDataInitHelp.dataSet(data, PaySheetEnum.PAY_TYPE.getAttr(), paymentData.get(PayPlanEnum.PAYMENT_METHOD.getAttr()));
                    SaasDataInitHelp.dataSet(data, PaySheetEnum.MEMO.getAttr(),paymentData.get(PayPlanEnum.MEMO.getAttr()));
                    SaasDataInitHelp.dataSet(data, PaySheetEnum.REAL_PAY_TIME.getAttr(), paymentData.get(PayPlanEnum.REAL_PAY_TIME.getAttr()));
                    Long purchaseId = FastJsonHelper.getLongOrDefaultFromFormData(paymentData, PayPlanEnum.LINK_PURCHASE.getAttr(), 0L);
                    if ( Objects.nonNull(payPlanDTO.getBelonger()) ) {
                        String belonger = payPlanDTO.getBelonger();
                        data.put(PaySheetEnum.BELONG_ID.getAttr(), Arrays.asList(belonger));
                    }
                    data.put(PaySheetEnum.PAY_SHEET_TYPE.getAttr(), PaySheetTypeEnum.WRITE_OFF_PAY.getCode());
                    data.put(PaySheetEnum.LINK_PURCHASE.getAttr(), Arrays.asList(purchaseId));
                    data.put(PaySheetEnum.PAY_PLAN.getAttr(), Arrays.asList(item.getId()));
                    data.put(PaySheetEnum.SUPPLIER_LINK_TEXT.getAttr(), paymentData.getString(PayPlanEnum.LINK_SUPPLIER_LINK_TEXT.getAttr()));
                    data.put(PaySheetEnum.PURCHASE_LINK_TEXT.getAttr(), Arrays.asList(paymentData.getString(PayPlanEnum.LINK_PURCHASE_LINK_TEXT.getAttr())));
                    data.put(PaySheetEnum.PAY_PLAN_LINK_TEXT.getAttr(), Arrays.asList(item.getSerialNo()));
                    if ( Objects.nonNull(fundAccountEntity) ) {
                        data.put(PaySheetEnum.FUND_ACCOUNT.getAttr(), fundAccountEntity.getId().toString());
                    }
                    updatePayPlanMap.put(StringConstant.SAAS_LINK_BUSINESS_ID, item.getId());
                    updatePayPlanMap.put(PayPlanEnum.LINK_PURCHASE.getSaasAttr(), paymentData.getLong(PayPlanEnum.LINK_PURCHASE.getAttr()));
                    updatePayPlanMap.put(PayPlanEnum.AMOUNT.getSaasAttr(), paymentData.getDouble(PayPlanEnum.AMOUNT.getAttr()));
                    updatePayPlanMap.put(PayPlanEnum.ESTIMATE_TIME.getSaasAttr(), paymentData.getLong(PayPlanEnum.ESTIMATE_TIME.getAttr()));
                } catch (XbbException e) {
                    LOG.error("",e);
                }
                payPlanSheetInsertDTO.setData(data);
                payPlanSheetInsertDTO.setSerialNo(serialNo);
                payPlanSheetList.add(payPlanSheetInsertDTO);
                needUpdatePayPlanList.add(updatePayPlanMap);
            });
            Set<Long> approvalPayIds = new HashSet<>();
            if(!Objects.equals(payPlanDTO.getIsImport(), 1) && Objects.nonNull(paasFormEntityExt) && Objects.equals(paasFormEntityExt.getIsProcessForm(), 1)){
                Iterator<PayPlanSheetInsertDTO> iterator = payPlanSheetList.iterator();
                while (iterator.hasNext()) {
                    PayPlanSheetInsertDTO payPlanSheetInsertDTO = iterator.next();
                    StartProcessDTO startProcessDTO = new StartProcessDTO();
                    BeanUtil.copyProperties(payPlanDTO, startProcessDTO);
                    BeanUtil.copyProperties(payPlanSheetInsertDTO, startProcessDTO);
                    startProcessDTO.setFormId(paasFormEntityExt.getId());
                    startProcessDTO.setData(payPlanSheetInsertDTO.getData());
                    startProcessDTO.setFormDataId(0L);
                    startProcessDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                    startProcessDTO.setBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode());
                    if (payPlanDTO.getProcessCreatorId() == null) {
                        startProcessDTO.setCreatorId(payPlanDTO.getUserId());
                    } else {
                        startProcessDTO.setCreatorId(payPlanDTO.getProcessCreatorId());
                    }

                    StartProcessVO startProcessVO = processStartHelp.startProcess(startProcessDTO, null);
                    if (Objects.isNull(startProcessVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.START_PROCESS_ERROR);
                    }
                    if (Objects.equals(startProcessVO.getNoApprovalRequired(), 0)) {
                        JSONArray payPlanSetIdArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(payPlanSheetInsertDTO.getData(), PaySheetEnum.PAY_PLAN.getAttr(), new JSONArray());
                        for ( Object payPlanId:payPlanSetIdArr) {
                            if ( Objects.nonNull(payPlanId) ) {
                                approvalPayIds.add(Long.valueOf(payPlanId.toString()));
                            }
                        }
                        iterator.remove();
                    }
                }
            }
            // 进审批了改付款状态为未付款
            if (!approvalPayIds.isEmpty()) {
                proUpdateHelp.updateByIds(XbbRefTypeEnum.PAY_PLAN.getCode(), payPlanDTO.getCorpid(), new ArrayList<>(approvalPayIds), PayPlanEnum.STATUS.getAttr(), PayPlanStatusEnum.UN_RECEIVABLES.getCode());
            }
            if(!payPlanSheetList.isEmpty()) {
                PayPlanSheetInsertBatchDTO payPlanSheetInsertBatchDTO = new PayPlanSheetInsertBatchDTO();
                BeanUtil.copyProperties(payPlanDTO, payPlanSheetInsertBatchDTO);
                payPlanSheetInsertBatchDTO.setPayPlanSheetList(payPlanSheetList);
                payPlanSheetService.insertBatch(payPlanSheetInsertBatchDTO, payPlanDTO.getProcessCreatorId());
                if (!needUpdatePayPlanList.isEmpty()) {
                    for (Map<String, Object> payment : needUpdatePayPlanList) {
                        JSONObject jsonObject = new JSONObject();
                        Double payMoney = (Double)payment.getOrDefault(PayPlanEnum.AMOUNT.getSaasAttr(), 0D);
                        jsonObject.put(PayPlanEnum.REAL_AMOUNT.getAttr(), payMoney);
                        jsonObject.put(PayPlanEnum.UN_AMOUNT.getAttr(), 0D);
                        jsonObject.put(PayPlanEnum.REAL_PAY_TIME.getAttr(), (Long)payment.getOrDefault(PayPlanEnum.ESTIMATE_TIME.getSaasAttr(), 0L));
                        jsonObject.put(PayPlanEnum.STATUS.getAttr(), PayPlanStatusEnum.RECEIVABLES.getCode());
                        Long payId = (Long)payment.getOrDefault(StringConstant.SAAS_LINK_BUSINESS_ID, 0L);
                        UpdateDataEntity updateData = ExplainUtil.getUpdateData(payId, jsonObject, payPlanDTO.getCorpid());
                        payPlanModel.updateBatch(Collections.singletonList(updateData), payPlanDTO.getCorpid());
                        // 更新现金毛利
                        Long purchaseId = (Long)payment.getOrDefault(PayPlanEnum.LINK_PURCHASE.getSaasAttr(), 0L);
                        purchaseService.updateProfit(payPlanDTO.getCorpid(), payMoney, purchaseId, payPlanDTO.getLinkPurchaseEntity());
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("payPlanServiceImpl.paySheet批量添加回款单出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public PaymentInsertBatchVO insertBatch(PayPlanInsertBatchDTO payPlanInsertBatchDTO, Boolean parentNew, String creatorId) throws XbbException {
        PaymentInsertBatchVO paymentInsertBatchVO = new PaymentInsertBatchVO();
        try {
            List<PaasFormDataEntityExt> paidForList = new ArrayList<>();
            List<PaasFormDataEntityExt> insertList = new ArrayList<>();
            String corpid = payPlanInsertBatchDTO.getCorpid();
            String userId = payPlanInsertBatchDTO.getUserId();
            String loginUserName = payPlanInsertBatchDTO.getLoginUserName();
            if (!Objects.equals(userId, creatorId)) {
                userId = creatorId;
                UserEntity userEntity = userModel.getByKeyIngoreDel(userId, corpid);
                if (Objects.nonNull(userEntity)) {
                    loginUserName = userEntity.getName();
                }
            }
            List<AddMuchFieldPojo> addBatchList = payPlanInsertBatchDTO.getDataList();
            // 批量新增流水号集合
            List<String> addBatchSerialNoList= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            addBatchList.forEach(addMuchFieldPojo -> addBatchSerialNoList.add(addMuchFieldPojo.getSerialNo()));
            String addBatchSerialNoStr = StringUtils.join(addBatchSerialNoList, "，");

            List<PayPlanEntityExt> formDataList = new ArrayList<>();
            //主要用于绑定付款计划与团队的信息，只有编号是唯一值，所以编号-》团队
            Map<String, AddMuchFieldPojo> serialTeamMap = new HashMap<>();
            addBatchList.forEach((item)->{
                PayPlanEntityExt payPlanEntityExt = new PayPlanEntityExt();
                BeanUtil.copyProperties(item, payPlanEntityExt);
                payPlanEntityExt.setCorpid(corpid);
                payPlanEntityExt.setAppId(payPlanInsertBatchDTO.getAppId());
                payPlanEntityExt.setMenuId(payPlanInsertBatchDTO.getMenuId());
                payPlanEntityExt.setFormId(payPlanInsertBatchDTO.getFormId());
                payPlanEntityExt.setData(item.getData());
                JSONObject data = item.getData();
                String status = data.getString(PayPlanEnum.STATUS.getAttr());
                data.put(PayPlanEnum.UN_AMOUNT.getAttr(), data.getDouble(PayPlanEnum.AMOUNT.getAttr()));
                if(PayPlanStatusEnum.UN_RECEIVABLES.getCode().equals(status)) {
                    data.remove(PayPlanEnum.BELONGER.getAttr());
                }
                fundHelp.removeNotInMapping(data);
                // 在添加回款单和付款单的时候再更新金额时间，因为可能进了审批
                if(PayPlanStatusEnum.RECEIVABLES.getCode().equals(status)) {
                    Long realPayTime = data.getLong(PayPlanEnum.ESTIMATE_TIME.getAttr());
                    realPayTime = Objects.isNull(realPayTime) || Objects.equals(realPayTime,0L) ? DateTimeUtil.getInt() : realPayTime;
                    data.put(PayPlanEnum.REAL_PAY_TIME.getAttr(),realPayTime);
                    paidForList.add(payPlanEntityExt);
                }
                payPlanEntityExt.setData(data);
                payPlanEntityExt.setCreatorId(creatorId);
                //TODO haibin.zhang 对于回款或者saas业务部门是否必要
                payPlanEntityExt.setDepartmentId(1L);
                if (Objects.nonNull(item.getDepartmentId())) {
                    payPlanEntityExt.setDepartmentId(item.getDepartmentId());
                }
                if (StringUtil.isNotEmpty(item.getOwnerId())) {
                    payPlanEntityExt.setOwnerId(item.getOwnerId());
                } else {
                    payPlanEntityExt.setOwnerId(creatorId);
                }
                payPlanEntityExt.setFlowStatus(FlowStatusEnum.NOT_NEED_APPROVAL.getType());
                long now = DateUtil.getInt();
                payPlanEntityExt.setAddTime(now);
                payPlanEntityExt.setUpdateTime(now);
                serialTeamMap.put(item.getSerialNo(), item);
                formDataList.add(payPlanEntityExt);
            });
            paymentInsertBatchVO.setPaidForList(paidForList);
            List<PayPlanEntityExt> payPlanEntityExtList = payPlanModel.insertBatch(formDataList);
            insertList.addAll(payPlanEntityExtList);
            paymentInsertBatchVO.setInsertList(insertList);
            List<Long> payPlanIdList = new ArrayList<>();
            JSONObject data = payPlanEntityExtList.get(0).getData();
            Long purchaseId  = data.getLong(PayPlanEnum.LINK_PURCHASE.getAttr());
            Long supplierId = data.getLong(PayPlanEnum.LINK_SUPPLIER.getAttr());
            for (PayPlanEntityExt payPlanEntityExt : payPlanEntityExtList){
                payPlanIdList.add(payPlanEntityExt.getId());
            }
            //普通应收款走的方法
            teamDataHelp.savePayAndpaymentBatchBusUserTeam(payPlanEntityExtList, serialTeamMap, payPlanInsertBatchDTO.getLoginUser());
            // 记录日志
            if(formDataList.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_ADD_FORM_DETAIL), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(), formDataList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(PaySheetEnum.PAY_PLAN_NO.getAttrName());
                infoArrPojo.setContent(addBatchSerialNoStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.NEW,
                        "", "", memo, payPlanInsertBatchDTO.getHttpHeader());
            } else if (Objects.equals(formDataList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_WORK), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(), addBatchSerialNoStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.NEW,
                        formDataList.get(0).getId().toString(), addBatchSerialNoStr, memo, payPlanInsertBatchDTO.getHttpHeader());
            }
        } catch (Exception e) {
            LOG.error("payPlanServiceImpl.insertBatch数据库保存表单数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return paymentInsertBatchVO;
    }

    /**
     * 获取付款团队
     *  @param purchaseId
     * @param supplierId
     * @param payPlanUserEntityList
     * @param payId
     * @param entity
     * @param isMain
     * @param corpid
     */
    private void getPayPlanUserTeam(Long purchaseId, Long supplierId, List<PayPlanUserEntity> payPlanUserEntityList, Long payId, ReturnUserAndDepartmentPojo entity, Integer isMain, String corpid) {
        PayPlanUserEntity payPlanUserEntity = new PayPlanUserEntity();
        payPlanUserEntity.setCorpid(corpid);
        payPlanUserEntity.setIsMain(isMain);
        payPlanUserEntity.setUserId(entity.getId().toString());
        payPlanUserEntity.setUserName(entity.getName());
        payPlanUserEntity.setId(null);
        payPlanUserEntity.setDataId(payId);
        payPlanUserEntity.setSupplierId(supplierId);
        payPlanUserEntity.setPurchaseId(purchaseId);
        payPlanUserEntityList.add(payPlanUserEntity);
    }

    @Override
    public PaymentUpdateBatchMuchFieldVO updateBatchMuchField(PayPlanUpdateBatchMuchFieldDTO payPlanUpdateBatchMuchFieldDTO, boolean source, Map<String, FieldAttrEntity> explainMap) throws XbbException {
        PaymentUpdateBatchMuchFieldVO paymentUpdateBatchMuchFieldVO = new PaymentUpdateBatchMuchFieldVO();
        // 批量更新流水号集合
        List<AddMuchFieldPojo> updateBatchList = payPlanUpdateBatchMuchFieldDTO.getDataList();
        List<String> updateBatchSerialNoList= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        try {
            String corpid = payPlanUpdateBatchMuchFieldDTO.getCorpid();
            String userId = payPlanUpdateBatchMuchFieldDTO.getUserId();
            Map<String, Object> map = BeanUtil.convertBean2Map(payPlanUpdateBatchMuchFieldDTO, true);
            List<Long> idList = new ArrayList<>();
            List<PayPlanEntityExt> updateDataList = new ArrayList<>();
            List<AddMuchFieldPojo> payPlanList = new ArrayList<>();
            Map<Long, AddMuchFieldPojo> dataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            updateBatchList.forEach((item)-> {
                idList.add(item.getId());
                JSONObject jsonObject = item.getData();
                String status = jsonObject.getString(PayPlanEnum.STATUS.getAttr());
                // 未付款状态的付款计划，保证 未付金额 与 计划付款金额 一致
                if ( Objects.equals(jsonObject.getString(PayPlanEnum.STATUS.getAttr()), PayPlanStatusEnum.UN_RECEIVABLES.getCode()) ) {
                    jsonObject.put(PayPlanEnum.UN_AMOUNT.getAttr(), jsonObject.getDouble(PayPlanEnum.AMOUNT.getAttr()));
                }
                if ( PayPlanStatusEnum.RECEIVABLES.getCode().equals(status) ) {
                    payPlanList.add(item);
                }
                dataMap.put(item.getId(), item);
//                updateDataList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
            });
            map.put("ids", idList);
            map.put("del", DelEnum.NORMAL.getDel());
            List<PayPlanEntityExt> list = payPlanModel.findEntitys(map);
            List<Long> esDeleteList = new ArrayList<>();
            //主要用于绑定应收款与团队的信息，只有编号是唯一值，所以编号-》团队
            Map<String, AddMuchFieldPojo> serialTeamMap = new HashMap<>();
            if (list == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            } else {
                Set<Long> idSet = new HashSet<>();
                for(PayPlanEntityExt payPlanEntityExt: list) {
                    updateBatchSerialNoList.add(payPlanEntityExt.getSerialNo());
                    JSONObject dbData = payPlanEntityExt.getData();
                    AddMuchFieldPojo addMuchFieldPojo = dataMap.getOrDefault(payPlanEntityExt.getId(),new AddMuchFieldPojo());
                    serialTeamMap.put(payPlanEntityExt.getSerialNo(), addMuchFieldPojo);
                    String oldStatus = dbData.getString(PayPlanEnum.STATUS.getAttr());
                    if (Objects.equals(dbData.getString(PayPlanEnum.STATUS.getAttr()), addMuchFieldPojo.getData().getString(PayPlanEnum.STATUS.getAttr()))) {
                        payPlanList.removeIf(paid -> Objects.equals(paid.getId(), payPlanEntityExt.getId()));
                    }
                    for (Map.Entry<String,Object> entry : addMuchFieldPojo.getData().entrySet()){
                        PayPlanStatusEnum payPlanStatusEnum = PayPlanStatusEnum.getByCode(oldStatus);
                        Boolean isEdit = PayPlanEnum.getUnableEditAttrMap(false,payPlanStatusEnum, entry.getKey());
                        if ( isEdit ){
                            dbData.put(entry.getKey(),entry.getValue());
                        }
                    }
                    if (StringUtil.isNotEmpty(addMuchFieldPojo.getSerialNo())) {
                        payPlanEntityExt.setSerialNo(addMuchFieldPojo.getSerialNo());
                    }
                    if (Objects.nonNull(addMuchFieldPojo.getDepartmentId())) {
                        payPlanEntityExt.setDepartmentId(addMuchFieldPojo.getDepartmentId());
                    }
                    fundHelp.removeNotInMapping(dbData);
                    payPlanEntityExt.setData(dbData);
                    updateDataList.add(payPlanEntityExt);
                    idSet.add(payPlanEntityExt.getId());
                }
                for(Long id : idList) {
                    if (!idSet.contains(id)) {
                        esDeleteList.add(id);
                    }
                }
            }
            // 删除数据库没有，但是es有的数据
            if (!esDeleteList.isEmpty()) {
                paasEsModel.deleteBatch(esDeleteList, corpid, DelEnum.DELETE.getDel(), IndexTypeEnum.IDX_SAAS_PAY_PLAN);
            }
            paymentUpdateBatchMuchFieldVO.setPaidForList(payPlanList);
            if (!updateDataList.isEmpty()) {
                payPlanHelp.updateBatch(updateDataList, corpid, explainMap);
                teamDataHelp.savePayAndpaymentBatchBusUserTeam(updateDataList, serialTeamMap, payPlanUpdateBatchMuchFieldDTO.getLoginUser());
            }

            // 记录日志
            if(source){
                String updateBatchSerialNoStr = StringUtils.join(updateBatchSerialNoList, "，");
                String loginUserName = payPlanUpdateBatchMuchFieldDTO.getLoginUserName();
                if(updateDataList.size() > 1){
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_UPDATE_FORM_DETAIL), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(), updateDataList.size());
                    List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    InfoArrPojo infoArrPojo = new InfoArrPojo();
                    infoArrPojo.setTitle(PaySheetEnum.PAY_PLAN_NO.getAttrName());
                    infoArrPojo.setContent(updateBatchSerialNoStr);
                    infoArrPojoList.add(infoArrPojo);
                    mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.EDIT,
                            "", "", memo, payPlanUpdateBatchMuchFieldDTO.getHttpHeader());
                } else if (Objects.equals(updateDataList.size(), 1)){
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_WORK), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(), updateBatchSerialNoStr);
                    mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.EDIT,
                            updateDataList.get(0).getId().toString(), updateBatchSerialNoStr, memo, payPlanUpdateBatchMuchFieldDTO.getHttpHeader());
                }
            }
        }catch (Exception e) {
            LOG.error("payPlanServiceImpl.updateBatchMuchField数据库批量更新出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return paymentUpdateBatchMuchFieldVO;
    }

    @Override
    public PayPlanDeleteBatchVO deleteBatch(PayPlanDeleteBatchDTO payPlanDeleteBatchDTO) throws XbbException {
        PayPlanDeleteBatchVO payPlanDeleteBatchVO = new PayPlanDeleteBatchVO();
        try {
            String corpid = payPlanDeleteBatchDTO.getCorpid();
            List<Long> idIn = payPlanDeleteBatchDTO.getDataIdList();
            idIn.removeIf(id->Objects.isNull(id));
            List<PaasFormDataEntityExt> payPlanList = new ArrayList<>();
            List<String> no= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!idIn.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termsQuery("id", idIn));
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                if (Objects.nonNull(payPlanDeleteBatchDTO.getStatus())) {
                    boolQueryBuilder.filter(termQuery("data."+PayPlanEnum.STATUS.getAttr(), payPlanDeleteBatchDTO.getStatus()));
                }
                boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                List<String> fieldList = new ArrayList<>();
                fieldList.add(StringConstant.DATA_ID);
                fieldList.add(FieldTypeEnum.SERIALNO.getAlias());
                payPlanList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAY_PLAN, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                if (Objects.isNull(payPlanList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                //查询编号
                for(PaasFormDataEntityExt entityExt : payPlanList){
                    String sheetNo = entityExt.getSerialNo();
                    no.add(sheetNo);
                }
                if(payPlanList.size() != idIn.size()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.ONLY_DEL_UN_RECEIVABLES);
                }

                Set<Long> inApprovalIdList = new HashSet<>();
                Set<Long> inApprovalIdPurchaseInvoiceList = new HashSet<>();

                if (commonHelp.isOpenWorkFlow(corpid)) {
                    // 开启工作流的时候从业务数据主表获取审批中数据
                    boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.filter(termsQuery(PaySheetEnum.getEsAttr4Keyword(PaySheetEnum.PAY_PLAN), idIn));
                    boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET.getType()));
                    List<PaasFormDataEntityExt> paySheetFormDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET,
                            boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(PaySheetEnum.getAttrConnectData(PaySheetEnum.PAY_PLAN), FieldTypeEnum.DATAID.getAlias()));

                    boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.filter(termsQuery(PurchaseInvoiceEnum.getEsAttr4Keyword(PurchaseInvoiceEnum.PAY_PLAN_ID), idIn));
                    boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PURCHASE_INVOICE.getType()));
                    List<PaasFormDataEntityExt> purchaseInvoiceFormDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PURCHASE_INVOICE,
                            boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(PurchaseInvoiceEnum.getAttrConnectData(PurchaseInvoiceEnum.PAY_PLAN_ID), FieldTypeEnum.DATAID.getAlias()));

                    if (paySheetFormDataList != null && !paySheetFormDataList.isEmpty()) {
                        for (PaasFormDataEntityExt processDataEntity : paySheetFormDataList) {
                            try {
                                JSONArray payPlanArr = processDataEntity.getData().getJSONArray(PaySheetEnum.PAY_PLAN.getAttr());
                                payPlanArr.forEach(item -> {
                                    inApprovalIdList.add(Long.valueOf(item.toString()));
                                });
                            } catch (Exception e) {
                                LOG.error("在审批中的关联的付款单", e);
                            }
                        }
                    }
                    if (CollectionsUtil.isNotEmpty(purchaseInvoiceFormDataList)) {
                        for (PaasFormDataEntityExt paasProcessDataEntity : purchaseInvoiceFormDataList) {
                            JSONArray payPlanArr = paasProcessDataEntity.getData().getJSONArray(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr());
                            payPlanArr.forEach(item -> {
                                inApprovalIdPurchaseInvoiceList.add(Long.valueOf(item.toString()));
                            });
                        }
                    }
                } else {
                    // 在审批中的关联的付款单
                    List<PaasProcessDataEntity> processDataEntityList = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.PAY_SHEET.getCode(), PaySheetEnum.PAY_PLAN.getAttr(), idIn, corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                    // 在审批中的关联进项开票
                    List<PaasProcessDataEntity> processPurchaseInvoiceDataEntityList = paasProcessDataModel.getInvoiceInApprovalDataByIdConditionJsonArray(XbbRefTypeEnum.PURCHASE_INVOICE.getCode(), PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr(), idIn, corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));

                    if (processDataEntityList != null && !processDataEntityList.isEmpty()) {
                        for (PaasProcessDataEntity processDataEntity : processDataEntityList) {
                            try {
                                JSONArray payPlanArr = JSONObject.parseObject(processDataEntity.getData()).getJSONArray(PaySheetEnum.PAY_PLAN.getAttr());
                                payPlanArr.forEach(item -> {
                                    inApprovalIdList.add(Long.valueOf(item.toString()));
                                });
                            } catch (Exception e) {
                                LOG.error("在审批中的关联的付款单", e);
                            }
                        }
                    }
                    if (CollectionsUtil.isNotEmpty(processPurchaseInvoiceDataEntityList)) {
                        for (PaasProcessDataEntity paasProcessDataEntity : processPurchaseInvoiceDataEntityList) {
                            JSONArray payPlanArr = JSONObject.parseObject(paasProcessDataEntity.getData()).getJSONArray(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr());
                            payPlanArr.forEach(item -> {
                                inApprovalIdPurchaseInvoiceList.add(Long.valueOf(item.toString()));
                            });
                        }
                    }
                }

                List<String> errorTypeList = new ArrayList<>();
                List<String> errorDataList = new ArrayList<>();
                for (PaasFormDataEntityExt paasFormDataEntityExt : payPlanList) {
                    if (inApprovalIdList.contains(paasFormDataEntityExt.getDataId())) {
                        if(!errorTypeList.contains(PayErrorCodeEnum.API_ERROR_226013.getMsg())){
                            errorTypeList.add(PayErrorCodeEnum.API_ERROR_226013.getMsg());
                        }
                        errorDataList.add(paasFormDataEntityExt.getSerialNo());
                        idIn.remove(paasFormDataEntityExt.getDataId());
                    }
                }
                for(PaasFormDataEntityExt paasFormDataEntityExt : payPlanList){
                    if(inApprovalIdPurchaseInvoiceList.contains(paasFormDataEntityExt.getDataId())){
                        if(!errorTypeList.contains(InvoiceErrorCodeEnum.API_ERROR_216047.getMsg())){
                            errorTypeList.add(InvoiceErrorCodeEnum.API_ERROR_216047.getMsg());
                        }
                        errorDataList.add(paasFormDataEntityExt.getSerialNo());
                        idIn.remove(paasFormDataEntityExt.getDataId());
                    }
                }
                if ( !idIn.isEmpty() ){
                    List<Object> idInObjects = new ArrayList<>(idIn.size());
                    for (Long id:idIn ){
                        idInObjects.add(id);
                    }
                    Map<Long, PaasFormDataEntityExt> paySheetEntityExtMap = fundHelp.getEsDataMapByLinkIds(XbbRefTypeEnum.PAY_SHEET,corpid, idInObjects, PaySheetEnum.PAY_PLAN.getAttr());
                    List<Long> paySheetPurchaseIds = new ArrayList<>();
                    for (PaasFormDataEntityExt paasFormDataEntityExt : payPlanList) {
                        PaasFormDataEntityExt paySheetEntityExt = paySheetEntityExtMap.get(paasFormDataEntityExt.getDataId());
                        if ( Objects.nonNull(paySheetEntityExt) ){
                            if(!errorTypeList.contains(PaymentErrorCodeEnum.API_ERROR_208050.getMsg())){
                                errorTypeList.add(PaymentErrorCodeEnum.API_ERROR_208050.getMsg());
                            }
                            errorDataList.add(paasFormDataEntityExt.getSerialNo());
                            paySheetPurchaseIds.add(paasFormDataEntityExt.getDataId());
                        }
                    }
                    idIn.removeAll(paySheetPurchaseIds);
                    //判断下面是否有发票
                    purchaseInvoiceService.checkBusinessDeleteHaveInvoice(idIn,corpid,XbbRefTypeEnum.PAY_PLAN,errorTypeList,errorDataList,null,null,null,null,null,null,null);
                }
                payPlanDeleteBatchVO.setErrorDataList(errorDataList);
                if (!errorDataList.isEmpty()) {
                    payPlanDeleteBatchVO.setErrorTypeList(errorTypeList);
                }
                payPlanDeleteBatchVO.setErrorDataMemo(SaasDeleteHelp.getErrorDataMemo(errorTypeList, errorDataList));
            }
            if (!idIn.isEmpty()) {
                payPlanDeleteBatchVO.setPayPlanList(payPlanList);
                payPlanDeleteBatchVO.setDeleteIds(idIn);
                if(BasicConstant.ONE.equals(payPlanDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(idIn.size())){
                    payPlanModel.deleteByKey(idIn.get(0),corpid);
                }else {
                    payPlanModel.deleteBatch(idIn, corpid, DelEnum.DELETE.getDel());
                }
                //删除对应付款计划的团队
                List<UserTeamEntity> userTeamEntities = userTeamHelp.getUserTeamList(idIn, corpid, XbbRefTypeEnum.PAY_PLAN.getCode(), false, null);
                if (CollectionsUtil.isNotEmpty(userTeamEntities)) {
                    List<Long> userIdIn = userTeamEntities.stream().map(UserTeamEntity::getId).collect(Collectors.toList());
                    payPlanUserModel.batchUpdateByUserIdIn(corpid, userIdIn, userTeamEntities, null, BasicConstant.ONE);
                }
            }
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, payPlanDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = payPlanDeleteBatchDTO.getUserId();
            String userName = payPlanDeleteBatchDTO.getLoginUserName();
            List<String> errorData = payPlanDeleteBatchVO.getErrorDataList();
            //取差集
            errorData.forEach(e -> no.removeIf(str -> Objects.equals(str, e)));
            String nameStr = StringUtils.join(no, "，");
            if(idIn.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.PAY_PLAN.getName(), idIn.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(PayPlanEnum.PAY_PLAN_NO.getAttrName());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.PayManage, operateTypeEnum,
                        "", "", memo, payPlanDeleteBatchDTO.getHttpHeader());
            } else if (Objects.equals(idIn.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.PAY_PLAN.getName(), nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PayManage, operateTypeEnum,
                        idIn.get(0).toString(), nameStr, memo, payPlanDeleteBatchDTO.getHttpHeader());
            }
            payPlanDeleteBatchVO.setDeleteIds(idIn);
        } catch (XbbException e){
            throw e;
        }catch (Exception e) {
            LOG.error("payPlanServiceImpl.deleteBatch批量删除出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return payPlanDeleteBatchVO;
    }


    @Override
    public PayPlanDeleteBatchVO deleteBatchByPurchaseId(PayPlanDeleteBatchDTO payPlanDeleteBatchDTO) throws XbbException {
        PayPlanDeleteBatchVO payPlanDeleteBatchVO = new PayPlanDeleteBatchVO();
        try {
            List<Long> idIn = payPlanDeleteBatchDTO.getDataIdList();
            if (Objects.isNull(idIn) || idIn.isEmpty()) {
                payPlanDeleteBatchVO.setPayPlanList(new ArrayList<>());
                return payPlanDeleteBatchVO;
            }
            String corpid = payPlanDeleteBatchDTO.getCorpid();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID+StringConstant.POINT+StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termsQuery(StringConstant.JSON_DATA+StringConstant.POINT + PayPlanEnum.LINK_PURCHASE.getAttr()+StringConstant.POINT+StringConstant.KEY_WORD, idIn));
            boolQueryBuilder.filter(termQuery("del", 0));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(StringConstant.DATA_ID);
            fieldList.add(FieldTypeEnum.SERIALNO.getAlias());
            List<PaasFormDataEntityExt> payPlanList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAY_PLAN, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
            if (Objects.isNull(payPlanList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<Long> payPlanIdIn = new ArrayList<>();
            List<String> delBatchSerialNoList= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaasFormDataEntityExt item : payPlanList) {
                if (Objects.isNull(item.getDataId())) {
                    continue;
                }
                payPlanIdIn.add(item.getDataId());
                delBatchSerialNoList.add(item.getSerialNo());
            }
            if (!payPlanIdIn.isEmpty()) {
                payPlanDeleteBatchDTO.setDataIdList(payPlanIdIn);
                payPlanModel.deleteBatch(payPlanIdIn, corpid, DelEnum.DELETE.getDel());

                // 删除付款单
//                payPlanDeleteBatchVO.setPayPlanList(payPlanList);
//                deletePayPlanSheetByPayPlan(payPlanDeleteBatchDTO, payPlanDeleteBatchVO);

                // 批量删除流水号集合
                String delBatchSerialNoStr = StringUtils.join(delBatchSerialNoList, "，");
                String userId = payPlanDeleteBatchDTO.getUserId();
                String loginUserName = payPlanDeleteBatchDTO.getLoginUserName();
                // 记录日志
                if(payPlanList.size() > 1){
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(), payPlanList.size());
                    List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    InfoArrPojo infoArrPojo = new InfoArrPojo();
                    infoArrPojo.setTitle(PayPlanEnum.PAY_PLAN_NO.getAttrName());
                    infoArrPojo.setContent(delBatchSerialNoStr);
                    infoArrPojoList.add(infoArrPojo);
                    mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.DELETE,
                            "", "", memo, payPlanDeleteBatchDTO.getHttpHeader());
                } else if (Objects.equals(payPlanList.size(), 1)){
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(), delBatchSerialNoStr);
                    mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.DELETE,
                            payPlanList.get(0).getDataId().toString(), delBatchSerialNoStr, memo, payPlanDeleteBatchDTO.getHttpHeader());
                }
            }
        }catch (XbbException e){
            throw e;
        }catch (Exception e) {
            LOG.error("payPlanServiceImpl.deleteBatchByPurchaseId 批量删除出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return payPlanDeleteBatchVO;
    }


    @Override
    public AddBatchDTO beforeSaveBatch(FormDataAddDTO formDataSaveDTO, boolean fromApproval) throws XbbException {
       return payPlanAnalyticalService.beforeSaveBatch(formDataSaveDTO, fromApproval);
    }

    @Override
    public void repeatBatch(PayPlanDTO payPlanDTO) throws XbbException {
        try {
            List<AddMuchFieldPojo> addBatchList = payPlanDTO.getAddBatchList();
            List<AddMuchFieldPojo> updateBatchList = payPlanDTO.getUpdateBatchList();
            List<AddMuchFieldPojo> delBatchList = payPlanDTO.getDelBatchList();
            // 需要插入的数据或需要更新数据不为空
            Long amount = 0L;
            Long contractId = 0L;
            List<String> serialNoList = new ArrayList<>();
            if(Objects.nonNull(addBatchList) && !addBatchList.isEmpty()) {
                for (AddMuchFieldPojo item : addBatchList) {
                    String serialNo = item.getSerialNo();
                    if (StringUtil.isNotEmpty(serialNo)) {
                        serialNoList.add(serialNo);
                    }
                    amount += item.getData().getLong(PaymentEnum.AMOUNT.getAttr());
                    JSONObject data = item.getData();
                    amount += data.getLong(PaymentEnum.AMOUNT.getAttr());
                    contractId = data.getLong(PaymentEnum.CONTRACT.getAttr());
                }
            }
            Map<String, Long> serialNoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if(Objects.nonNull(updateBatchList) && !updateBatchList.isEmpty()){
                for (AddMuchFieldPojo item : updateBatchList) {
                    String serialNo = item.getSerialNo();
                    if (StringUtil.isNotEmpty(serialNo)) {
                        serialNoList.add(serialNo);
                        serialNoMap.put(serialNo, item.getId());
                    }
                    JSONObject data = item.getData();
                    amount += data.getLong(PaymentEnum.AMOUNT.getAttr());
                    contractId = data.getLong(PaymentEnum.CONTRACT.getAttr());
                }
            }
            Long subtractedAmount = 0L;
            if(Objects.nonNull(delBatchList) && !delBatchList.isEmpty()){
                for (AddMuchFieldPojo item : delBatchList) {
                    JSONObject data = item.getData();
                    subtractedAmount += data.getLong(PaymentEnum.AMOUNT.getAttr());
                    contractId = data.getLong(PaymentEnum.CONTRACT.getAttr());
                }
            }
            // 获取新建的和更新计划收款金额总和减去删除的计划收款金额
            Long resultAmount = amount - subtractedAmount;
            PurchaseEntityExt purchaseEntityExt = purchaseModel.getByKey(contractId, payPlanDTO.getCorpid());
            if(Objects.isNull(purchaseEntityExt)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.CONTRACT_NOT_EXISTS);
            }
            JSONObject contractData = purchaseEntityExt.getData();
            Long contractAmount = contractData.getLong(ContractEnum.AMOUNT.getAttr());
            // 新建的和更新计划收款金额总和减去删除的计划收款金额不能大于合同金额
            //允许误差小于等于ConfigConstant.amountAccuracy
            if (Arith.sub(resultAmount, contractAmount) > ConfigConstant.amountAccuracy) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PAYMENT_NOT_MORE_THAN_CONTRACT);
            }
            if (!serialNoList.isEmpty()) {
                Set<String> serialSet = new HashSet<>();
                for (String serialNo : serialNoList) {
                    serialSet.add(serialNo);
                }
                if(serialNoList.size() != serialSet.size()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.SAME_DATA_EXISTS);
                }
                FormDataRepeatBatchDTO formDataRepeatBatchDTO = new FormDataRepeatBatchDTO();
                BeanUtil.copyProperties(payPlanDTO, formDataRepeatBatchDTO);
                formDataRepeatBatchDTO.setSerialNoList(serialNoList);
                FormDataRepeatBatchVO formDataRepeatBatchVO = paasFormDataService.repeatBatch(formDataRepeatBatchDTO);
                if(Objects.isNull(formDataRepeatBatchVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                List<PaasFormDataEntityExt> formDataList = formDataRepeatBatchVO.getFormDataList();
                if(Objects.isNull(formDataList)){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                if(!formDataList.isEmpty() && formDataList.size() > 1){
                    for (PaasFormDataEntityExt item : formDataList) {
                        // 根据编号获取数据id，如果id和数据库存储不一致，则为重复数据
                        if (!serialNoMap.isEmpty() && !serialNoMap.get(item.getSerialNo()).equals(item.getDataId())) {
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DUPLICATE_VALUE, "");
                        }
                    }
                }
            }

        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("payPlanServiceImpl.repeatBatch判重出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }


    /**
     * 判断付款的付款单是否有在审批中
     *
     * @param payPlanId 付款计划id
     * @param corpid    公司id
     * @return 创建时间： 2017-12-14 下午9:32:20
     * 修改时间：
     * @author chy
     */
    @Override
    public boolean payPlanApproval(Long payPlanId, String corpid) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("delIn", Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.APPROVE_STATUS.getDel()));
        param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        Integer count = payPlanSheetModel.getCountByOneCondition(PaySheetEnum.PAY_PLAN.getAttr(), payPlanId, param);
        return count > BasicConstant.ZERO;
    }


    @Override
    public void batchEditAttr(PayPlanEditAttrUpdateDTO payPlanEditAttrUpdateDTO) throws XbbException {
        try {
            String corpid = payPlanEditAttrUpdateDTO.getCorpid();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", payPlanEditAttrUpdateDTO.getDataIdList());
            List<PayPlanEntityExt> payPlanEntityList  = payPlanModel.findEntitys(param);
            if (Objects.isNull(payPlanEntityList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            //权限团队校验前置了
            List<Long> errorIdList = new ArrayList<>();
//            List<Long> errorIdList = userTeamHelp.batchTeamMembersCheckEditPermission(payPlanEditAttrUpdateDTO.getBusinessType(), payPlanEditAttrUpdateDTO.getSaasMark(),
//                    payPlanEditAttrUpdateDTO.getMenuId(), payPlanEditAttrUpdateDTO.getLoginUser(), payPlanEditAttrUpdateDTO.getDistributorMark(),
//                    payPlanEditAttrUpdateDTO.getDataIdList(), new HashMap<>());
            List<String> errorNameList = new ArrayList<>();
            for (PayPlanEntityExt payPlanEntityExt : payPlanEntityList) {
                if (errorIdList.contains(payPlanEntityExt.getId())) {
                    errorNameList.add(payPlanEntityExt.getSerialNo());
                }
            }
            String nameStr = org.apache.commons.lang.StringUtils.join(errorNameList, "、");
            if (CollectionUtils.isNotEmpty(errorNameList)) {
                throw new XbbException(UserTeamErrorCodeEnum.API_ERROR_271038.getCode(), String.format(UserTeamErrorCodeEnum.API_ERROR_271038.getMsg(), nameStr));
            }
            List<PayPlanUpdateDTO> payPlanList = new ArrayList<>();
            payPlanEditAttrUpdateDTO.getDataIdList().forEach((item)->{
                PayPlanUpdateDTO payPlan = new PayPlanUpdateDTO();
                payPlan.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(payPlanEditAttrUpdateDTO.getFieldEditedList());
                payPlan.setData(data);
                payPlanList.add(payPlan);
            });
            if (!payPlanList.isEmpty()) {
                PayPlanUpdateBatchDTO payPlanUpdateBatchDTO = new PayPlanUpdateBatchDTO();
                BeanUtil.copyProperties(payPlanEditAttrUpdateDTO, payPlanUpdateBatchDTO);
                payPlanUpdateBatchDTO.setPayPlanList(payPlanList);
                updateBatch(payPlanUpdateBatchDTO);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PayPlanEntityExt item : payPlanEntityList) {
                dataIdList.add(item.getId());
                String serialNo = item.getSerialNo();
                updataItemList.add(serialNo);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = payPlanEditAttrUpdateDTO.getUserId();
            String loginUserName = payPlanEditAttrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = payPlanEditAttrUpdateDTO.getFieldType();
            Boolean isFieldDependence = payPlanEditAttrUpdateDTO.getIsFieldDependence();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence,payPlanEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(payPlanEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.PAY_PLAN.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.EDIT,
                        "", "", memo, payPlanEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.PAY_PLAN.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.PayManage, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, payPlanEditAttrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("instockService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public List<PaasFormDataEntityExt> getPayPlanEsDataListByPurchaseId(String corpid, Long purchaseId) throws XbbException {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("data." + PayPlanEnum.LINK_PURCHASE.getAttr(), purchaseId));
        boolQueryBuilder.filter(termQuery("del", 0));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PAY_PLAN.getType()));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PAY_PLAN.getIndex());
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, PaasConstant.ES_MAX_PAGE_SIZE);
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
        return esEntities.getContent();
    }

    @Override
    public void formatLinkAddExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException{
        JSONObject linkFormData = handlerExplainInLinkItemDTO.getLinkFormData();
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        PaasFormDataEntityExt paasFormDataEntityExt = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt();
        FieldAttrEntity linkCustomerField = new FieldAttrEntity();
        FieldAttrEntity linkContractField = new FieldAttrEntity();
        for(FieldAttrEntity fieldAttrEntity :explainList) {
            if (Objects.equals(fieldAttrEntity.getAttr(), PayPlanEnum.LINK_SUPPLIER.getAttr())) {
                linkCustomerField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), PayPlanEnum.LINK_PURCHASE.getAttr())) {
                linkContractField = fieldAttrEntity;
            }
        }
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
        switch (redundantTemplateTypeEnum) {
            case SUPPLIER:
                String supplierName = FastJsonHelper.getStringOrDefaultFromFormData(linkFormData, SupplierEnum.SUPPLIER_NAME.getAttr(), "");
                linkCustomerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, supplierName));
                break;
            case PURCHASE:
                String purchaseNo = paasFormDataEntityExt.getSerialNo();
                DefaultAttrPoJo defaultAttrPoJo = saasUpdateHelp.getDefaultAttrPojo(linkDataId, purchaseNo);
                String totalMoney = linkFormData.getString(PurchaseEnum.TOTAL_MONEY.getAttr());
                Object linkFormValueObject = defaultAttrPoJo.getLinkFormValue();

                FormDataUpdateGetDTO formDataUpdateGetDTO = new FormDataUpdateGetDTO();
                BeanUtil.copyProperties(handlerExplainInLinkItemDTO,formDataUpdateGetDTO);
                formDataUpdateGetDTO.setDataId(handlerExplainInLinkItemDTO.getLinkDataId());
                Double finishAmount = fundMoneyHelp.getWriteOffAmount(formDataUpdateGetDTO,XbbRefTypeEnum.PURCHASE.getCode());

                if (linkFormValueObject instanceof JSONArray) {
                    JSONArray linkFormValueArray = (JSONArray)linkFormValueObject;
                    for (Object linkFormValue : linkFormValueArray) {
                        JSONObject linkFormValueJson = (JSONObject)linkFormValue;
                        linkFormValueJson.put(PurchaseEnum.TOTAL_MONEY.getAttr(), totalMoney);
                        linkFormValueJson.put(StringConstant.FINISH_AMOUNT, finishAmount);
                    }
                }
                linkContractField.setDefaultAttr(defaultAttrPoJo);

                JSONArray linkSupplierArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PurchaseEnum.SUPPLIER_ID.getAttr(), new JSONArray());
                linkCustomerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkSupplierArr));
                break;
            default:
                throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
        }
    }

    @Override
    public void dataConsistencyUpdateSupplier(String corpid, Long dataId, String name) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0))
                    .filter(termQuery(PayPlanEnum.getEsAttr4Keyword(PayPlanEnum.LINK_SUPPLIER), dataId));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAY_PLAN, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<PayPlanEntityExt> payPlanEntityExtList = payPlanModel.findEntitys(param);

            if (Objects.nonNull(payPlanEntityExtList) && !payPlanEntityExtList.isEmpty()) {
                List<PayPlanUpdateDTO> payPlanUpdateDTOList = new ArrayList<>();
                for (PayPlanEntityExt entityExt : payPlanEntityExtList) {
                    PayPlanUpdateDTO payPlanUpdateDTO = new PayPlanUpdateDTO();
                    payPlanUpdateDTO.setId(entityExt.getId());
                    JSONObject data = new JSONObject();
                    data.put(PayPlanEnum.LINK_SUPPLIER_LINK_TEXT.getAttr(), name);
                    payPlanUpdateDTO.setData(data);
                    payPlanUpdateDTOList.add(payPlanUpdateDTO);
                }
                PayPlanUpdateBatchDTO opportunityUpdateBatchDTO = new PayPlanUpdateBatchDTO();
                opportunityUpdateBatchDTO.setCorpid(corpid);
                opportunityUpdateBatchDTO.setPayPlanList(payPlanUpdateDTOList);
                updateBatch(opportunityUpdateBatchDTO);
            }

        } catch (Exception e) {
            LOG.error("payPlanServiceImpl.dataConsistencyUpdateSupplier 出错， corpid=" + corpid + "  contactId=" + dataId + "  contactName=" + name, e);
        }
    }

    @Override
    public void updateBatchByBusinessRule(OperationDTO operationDTO) throws XbbException {
        try {
            String corpid = operationDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = operationDTO.getFormDataList();
            List<UpdateDataEntity> updateList = operationDTO.getUpdateList();
            if(!updateList.isEmpty()){
                payPlanModel.updateBatch(updateList, corpid);
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(operationDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        }catch (Exception e){
            LOG.error("payPlanService.updateBatchByBusinessRule 根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    public PayPlanUpdateBatchVO updateBatch(PayPlanUpdateBatchDTO opportunityUpdateBatchDTO) throws XbbException {
        PayPlanUpdateBatchVO opportunityUpdateBatchVO = new PayPlanUpdateBatchVO();
        try {
            String corpid = opportunityUpdateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateList = new ArrayList<>();
            List<PayPlanUpdateDTO> payPlanList = opportunityUpdateBatchDTO.getPayPlanList();
            if (Objects.nonNull(payPlanList) && !payPlanList.isEmpty()) {
                payPlanList.forEach((item)->{
                    updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
            }
            if (!updateList.isEmpty()) {
                payPlanModel.updateBatch(updateList, corpid);
            }
        } catch (Exception e) {
            LOG.error("opportunityServiceImpl.updateBatch 报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return opportunityUpdateBatchVO;
    }

    /**
     * 坏账还原
     *
     * @param payPlanBadReturnDTO
     * @return
     * @throws XbbException
     */
    @Override
    public PayPlanVO badDebtReturn(PayPlanBadReturnDTO payPlanBadReturnDTO) throws XbbException {
        Long paymentId = payPlanBadReturnDTO.getDataId();
        String corpid = payPlanBadReturnDTO.getCorpid();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termsQuery(PaySheetEnum.getEsAttr4Keyword(PaySheetEnum.PAY_PLAN),Arrays.asList(paymentId)));
        boolQueryBuilder.filter(termQuery(PaySheetEnum.getEsAttr4Keyword(PaySheetEnum.PAY_SHEET_TYPE), PaySheetTypeEnum.BAD_PAY.getCode()));
        boolQueryBuilder.filter(termsQuery(BasicConstant.ALONE,Arrays.asList(SheetAloneEnum.PARENT.getCode(), SheetAloneEnum.NORMAL.getCode())));
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET,boolQueryBuilder,PaasFormDataEntityExt.class,null);
        if (paasFormDataEntityExtList.isEmpty()){
            return new PayPlanVO();
        }
        PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataEntityExtList.get(0);
        FormDataDeleteBatchDTO formDataDeleteBatchDTO = new FormDataDeleteBatchDTO();
        BeanUtil.copyProperties(payPlanBadReturnDTO, formDataDeleteBatchDTO);
        BeanUtil.copyProperties(paasFormDataEntityExt,formDataDeleteBatchDTO);
        formDataDeleteBatchDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        formDataDeleteBatchDTO.setBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode());
        formDataDeleteBatchDTO.setDataIdList(Collections.singletonList(paasFormDataEntityExt.getDataId()));
        saasDeleteHelp.deleteBatch(formDataDeleteBatchDTO);
        return new PayPlanVO();
    }

    @Override
    public List<UpdateDataEntity> handlePlan(SheetTypeEnum sheetTypeEnum, JSONObject sheetData, String corpid, Map<Long, Double> paymentIdToAmount, Set<Long> paymentIds) throws XbbException {
        Long sheetPaymentTime = sheetData.getLongValue(PaySheetEnum.REAL_PAY_TIME.getAttr());
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("idIn", paymentIds);
        param.put("corpid", corpid);
        List<PayPlanEntityExt> payments = payPlanModel.findEntitys(param);
        if (Objects.isNull(payments)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        List<UpdateDataEntity> updateList = new ArrayList<>();
        boolean isRedFlag = SheetTypeEnum.isRed(sheetTypeEnum);
        boolean isBadFlag = SheetTypeEnum.isBad(sheetTypeEnum);
        for (PayPlanEntityExt entityExt : payments) {
            String name = entityExt.getSerialNo();
            if (Objects.equals(entityExt.getDel(), DelEnum.DELETE.getDel())) {
                throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208032, PaymentErrorCodeEnum.API_ERROR_208032.getMsg(), XbbRefTypeEnum.PAY_PLAN.getName(), name);
            }
            Long paymentId = entityExt.getId();
            //当前付款计划的实付金额(新增)
            Double value = paymentIdToAmount.getOrDefault(paymentId, 0D);
            if (value == 0) {
                continue;
            }
            JSONObject data = entityExt.getData();
            Double tempAmount = value;
            Double planRealAmount = getDoubleOrDefaultFromFormData(data, PayPlanEnum.REAL_AMOUNT.getAttr(), 0D);
            Double unAmount = getDoubleOrDefaultFromFormData(data, PayPlanEnum.UN_AMOUNT.getAttr(), 0D);
            JSONObject updateData = new JSONObject();
            if (isRedFlag) {
                if (Arith.sub(tempAmount , planRealAmount) > ConfigConstant.amountAccuracy) {
                    //红冲，限制红冲金额小于等于付款金额
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.DETAIL_BEYOND_AMOUNT_RED, XbbRefTypeEnum.PAY_PLAN.getName() + name);
                }
                //红冲的，把金额置为负数。用tempAmount计算金额是否合法
                value = Arith.mul(value, -1);
            } else {
                //普通付款（已核销、预付款核销、坏账），限制付款金额小于等于未付金额
                if (Arith.sub(value , unAmount) > ConfigConstant.amountAccuracy) {
                    if (isBadFlag) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.DETAIL_BEYOND_AMOUNT_BAD, XbbRefTypeEnum.PAY_PLAN.getName(), name);
                    }
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.DETAIL_BEYOND_AMOUNT_PAY, XbbRefTypeEnum.PAY_PLAN.getName(), name);
                }
                if (!isBadFlag) {
                    //坏账，红冲不需要置付款计划的实际付款日期，只有已核销、预付款核销才需要
                    Long realPayTime = data.getLongValue(PayPlanEnum.REAL_PAY_TIME.getAttr());
                    if (realPayTime < sheetPaymentTime) {
                        updateData.put(PayPlanEnum.REAL_PAY_TIME.getAttr(), sheetPaymentTime);
                    }
                }
            }
            //处理付款计划的已付、未付、付款状态
            Double planAmount = getDoubleOrDefaultFromFormData(data, PayPlanEnum.AMOUNT.getAttr(), 0D);
            Double badAmount = getDoubleOrDefaultFromFormData(data, PayPlanEnum.BAD_AMOUNT.getAttr(), 0D);
            if ( isRedFlag ) {
                updateData.put(PayPlanEnum.HAS_RED.getAttr(), HasRedEnum.HAS_RED.getCode());
            }
            handlePlanAmountStatus4Add(isBadFlag, value, updateData, planAmount, planRealAmount, unAmount, badAmount);
            UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(paymentId, updateData, corpid);
            updateList.add(updateDataEntity);
        }
        return updateList;
    }

    /**
     * 处理付款计划的已付、未付、付款状态：付款金额增加的情况（已核销、预付款核销、红冲-需确保金额为负数）
     * 注：坏账的优先级最高，如果有坏账金额，则付款状态要么是坏账、要么是部分坏账
     * @param isBadFlag true坏账，false非坏账。当是坏账时，付款计划的状态直接置为坏账
     * @param amount 新传入的付款金额
     * @param updateData 要更新的data
     * @param planAmount 计划内的付款金额
     * @param planRealAmount 计划内的已付金额
     * @param unAmount 计划内的未付金额
     * @param badAmount 坏账金额
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void handlePlanAmountStatus4Add(boolean isBadFlag, Double amount, JSONObject updateData, Double planAmount, Double planRealAmount, Double unAmount, Double badAmount) {
        //未付减去amount，如果amount为负数，则为加
        unAmount = Arith.sub(unAmount, amount);
        String planStatus;
        if (isBadFlag) {
            if (Objects.equals(amount, planAmount)) {
                //坏账金额等于付款计划金额，则全部坏账，否则部分坏账
                planStatus = PayPlanStatusEnum.BAD_DEBT.getCode();
            }else{
                planStatus = PayPlanStatusEnum.PARTIAL_BAD_DEBT.getCode();
            }
            updateData.put(PayPlanEnum.BAD_AMOUNT.getAttr(), amount);
        } else {
            planStatus = saasPayPlanHelper.handleStatus(planAmount, unAmount, badAmount);
            //已付加上amount（坏账不需要加实付：坏账是坏的未付，只对未付金额减去坏账金额即可）
            amount = Arith.add(planRealAmount, amount);
            updateData.put(PayPlanEnum.REAL_AMOUNT.getAttr(), amount);
        }
        updateData.put(PayPlanEnum.STATUS.getAttr(), planStatus);
        updateData.put(PayPlanEnum.UN_AMOUNT.getAttr(), unAmount);
    }

    /**
     * Description: 格式化导出excelvalue
     *
     * @param importFormDataDTO 入参
     * @param titlePojoList     标题
     * @param rowGroupPojo      组
     * @param fieldAttrList     解释
     * @return FormDataAddDTO
     * @author chenshan
     * @date 2020/3/10 16:47
     * @since v1.0
     */
    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        // data 数据
        JSONObject dataJson = new JSONObject();
        Long linkSupplierId = 0L;
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);

        FieldAttrEntityForImport linkSupplierAttr = null;
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            if (Objects.equals(fieldAttrEntityForImport.getAttr(), PayPlanEnum.LINK_SUPPLIER.getAttr())) {
                linkSupplierAttr = fieldAttrEntityForImport;
                break;
            }
        }

        if (Objects.nonNull(linkSupplierAttr)) {
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, linkSupplierAttr.getAttrName(), null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            linkSupplierId = importHelper.formatSuppplier2SupplierId(cellValue.toString(), dataJson, linkSupplierAttr);
        }
        // 遍历数据
        for ( FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList ) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if (Objects.equals(attr, PayPlanEnum.LINK_SUPPLIER.getAttr())) {

            } else if ( Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType()) ) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else {
                if ( Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString()) ) {
                    continue;
                }
                if ( ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType()) ) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                } else if (Objects.equals(attr, PayPlanEnum.LINK_PURCHASE.getAttr()) ) {
                    importHelper.formatRelyBusiness(linkSupplierId, dataJson, fieldAttrEntityForImport, cellValue, PurchaseEnum.SUPPLIER_ID.getAttr());
                } else {
                    if ( Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType()) ) {
                        formDataAddDTO.setSerialNo(cellValue.toString());
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                        importHelper.formatLinkData(cellValue, fieldAttrEntityForImport, dataJson);
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                        importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttrEntityForImport, dataJson);
                    } else {
                        dataJson.put(attr, cellValue);
                    }
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    public Long formatLinkSupplier2SupplierId(ImportFormDataDTO importFormDataDTO, JSONObject dataJson, String value,FieldAttrEntityForImport fieldAttr) throws XbbException {
        SupplierEntityExt supplierEntityExt = supplierModel.getBySupplierName(importFormDataDTO.getCorpid(), value);
        Long linkSupplierId = supplierEntityExt.getId();
        JSONArray linkBusinessArr = new JSONArray();
        JSONObject linkSupplierObj = new JSONObject();
        linkSupplierObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, linkSupplierId);
        linkSupplierObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, supplierEntityExt.getData().getString(SupplierEnum.SUPPLIER_NAME.getAttr()));
        linkBusinessArr.add(linkSupplierObj);
        dataJson.put(fieldAttr.getAttr(), linkBusinessArr);
        return linkSupplierId;
    }

    @Override
    public void updateRollback(Collection<Long> idIn, String corpid) throws XbbException {
        if (Objects.isNull(idIn) || idIn.isEmpty()) {
            return;
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("idIn", idIn);
        List<PayPlanEntityExt> list = payPlanModel.findEntitysWithoutSub(param);
        if (Objects.nonNull(list)) {
            for (PayPlanEntityExt item : list) {
                PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                BeanUtil.copyProperties(item, paasFormDataEntity);
                proEsHelper.reductionEsInUpdate(paasFormDataEntity, item.getId(), corpid, IndexTypeEnum.IDX_SAAS_PAY_PLAN);
            }
        }
    }

    @Override
    public List<UpdateDataEntity> updatePlan4Del(String corpid, Set<String> errorTypeSet, Set<String> errorDataSet, Collection<Long> delIdList, SheetDeleteHandleRelateDTO sheetDeleteHandleRelateDTO) throws XbbException {
        Map<Long, Double> paymentIdToAmount = sheetDeleteHandleRelateDTO.getPaymentIdToAmount();
        Map<Long, Double> paymentIdToUnAmount = sheetDeleteHandleRelateDTO.getPaymentIdToUnAmount();
        Map<Long, Double> paymentIdToBad = sheetDeleteHandleRelateDTO.getPaymentIdToBad();
        Set<Long> paymentIds = sheetDeleteHandleRelateDTO.getPaymentIds();
        Map<Long, List<Long>> pidSheetIdListMap = sheetDeleteHandleRelateDTO.getPidSheetIdListMap();
        Map<Long, List<String>> pidSheetNoListMap = sheetDeleteHandleRelateDTO.getPidSheetNoListMap();
        List<String> delNoList = sheetDeleteHandleRelateDTO.getDelNoList();
        PayPlanEnum enumAmount = PayPlanEnum.AMOUNT;
        PayPlanEnum enumRealAmount = PayPlanEnum.REAL_AMOUNT;
        PayPlanEnum enumUnAmount = PayPlanEnum.UN_AMOUNT;
        PayPlanEnum enumBadAmount = PayPlanEnum.BAD_AMOUNT;
        PayPlanEnum enumRealPayTime = PayPlanEnum.REAL_PAY_TIME;
        List<String> fieldList = Arrays.asList(BasicConstant.ID, "del", PayPlanEnum.PAY_PLAN_NO.getAttr(), PayPlanEnum.getAttrConnectData(enumAmount), PayPlanEnum.getAttrConnectData(enumRealAmount), PayPlanEnum.getAttrConnectData(enumUnAmount), PayPlanEnum.getAttrConnectData(enumBadAmount), PayPlanEnum.getAttrConnectData(enumRealPayTime));
        List<PaasFormDataEntityExt> payments = formHelp.getFormListByIds4All(corpid, IndexTypeEnum.IDX_SAAS_PAY_PLAN, paymentIds, fieldList);
        List<UpdateDataEntity> updateList = new ArrayList<>();
        if (Objects.isNull(payments)) {
            //查不到关联数据，则不关联更新
            return updateList;
        }
        //再查询出除了allDelIdList之外关联了paymentIds的付款单（无父子、父付款单）
        String attrSheetType = PaySheetEnum.getAttrConnectData(PaySheetEnum.PAY_SHEET_TYPE);
        String attrPlan = PaySheetEnum.getAttrConnectData(PaySheetEnum.PAY_PLAN);
        List<String> notBadCodeList = PaySheetTypeEnum.getNotBadCodeList();
        Map<Long, List<PaasFormDataEntityExt>> sheetMap = formHelp.getSheetListMap(corpid, delIdList, paymentIds, IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET, attrSheetType, attrPlan, notBadCodeList);
        PaySheetEnum enumSheetPaymentTime = PaySheetEnum.REAL_PAY_TIME;
        for (PaasFormDataEntityExt entityExt : payments) {
            if (Objects.equals(entityExt.getDel(), DelEnum.DELETE.getDel())) {
                //付款计划已经删除，则跳过不处理
                continue;
            }
            JSONObject updateData = new JSONObject();
            Long paymentId = entityExt.getId();
            JSONObject planData = entityExt.getData();
            Double finishAmount = commonHelp.handleAttrAmount(enumRealAmount.getAttr(), paymentIdToAmount, paymentId, planData, updateData);
            //已付小于0，则不能更新该付款计划、且不能删除该付款计划对应的付款单集合
            if(finishAmount < BasicConstant.ZERO_DOUBLE){
                //封装不能删除信息，并从delIdList、delNoList移除
                commonHelp.removeInfoAndAmountBack4DelError(true, I18nMessageUtil.getMessage(ErrorMessageConstant.NON_ZERO_PURCHASE_PAY_PLAN_AMOUNT), errorTypeSet, errorDataSet, pidSheetNoListMap, pidSheetIdListMap, delIdList, delNoList, paymentId, sheetDeleteHandleRelateDTO);
                continue;
            }
            double unAmount = commonHelp.handleAttrAmount(enumUnAmount.getAttr(), paymentIdToUnAmount, paymentId, planData, updateData);
            //未付小于0，则不能更新该付款计划、且不能删除该付款计划对应的付款单集合
            if(unAmount < BasicConstant.ZERO_DOUBLE){
                //封装不能删除信息，并从delIdList、delNoList移除
                commonHelp.removeInfoAndAmountBack4DelError(true, I18nMessageUtil.getMessage(ErrorMessageConstant.NON_ZERO_PURCHASE_PAY_PLAN_AMOUNT_UN), errorTypeSet, errorDataSet, pidSheetNoListMap, pidSheetIdListMap, delIdList, delNoList, paymentId, sheetDeleteHandleRelateDTO);
                continue;
            }
            double badAmount = commonHelp.handleAttrAmount(enumBadAmount.getAttr(), paymentIdToBad, paymentId, planData, updateData);
            //坏账小于0，则不能更新该付款计划、且不能删除该付款计划对应的付款单集合
            if(badAmount < BasicConstant.ZERO_DOUBLE){
                //封装不能删除信息，并从delIdList、delNoList移除
                commonHelp.removeInfoAndAmountBack4DelError(true, I18nMessageUtil.getMessage(ErrorMessageConstant.NON_ZERO_PURCHASE_PAY_PLAN_AMOUNT_BAD), errorTypeSet, errorDataSet, pidSheetNoListMap, pidSheetIdListMap, delIdList, delNoList, paymentId, sheetDeleteHandleRelateDTO);
                continue;
            }
            if (updateData.size() == 0) {
                //已付、未付、坏账金额都没变动
                continue;
            }
            //处理其回款时间
            Long realPayTime = 0L;
            List<PaasFormDataEntityExt> sheetList = sheetMap.get(paymentId);
            int hasRed = 0;
            if (CollectionUtils.isNotEmpty(sheetList)) {
                for (PaasFormDataEntity sheet : sheetList) {
                    JSONObject data = sheet.getData();
                    Long sheetPaymentTime = data.getLong(enumSheetPaymentTime.getAttr());
                    String sheetType = data.getString(PaySheetEnum.PAY_SHEET_TYPE.getAttr());
                    if (realPayTime < sheetPaymentTime && PaySheetTypeEnum.isWriteOff(sheetType)) {
                        realPayTime = sheetPaymentTime;
                    }
                    if (PaySheetTypeEnum.isRed(sheetType)) {
                        hasRed = 1;
                    }
                }
            }
            updateData.put(PayPlanEnum.REAL_PAY_TIME.getAttr(), realPayTime);
            updateData.put(PayPlanEnum.HAS_RED.getAttr(), hasRed);
            //设置付款计划的状态
            Double planAmount = planData.getDoubleValue(PayPlanEnum.AMOUNT.getAttr());
            String planStatus = saasPayPlanHelper.handleStatus(planAmount, unAmount, badAmount);
            updateData.put(PayPlanEnum.STATUS.getAttr(), planStatus);
            UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(paymentId, updateData, corpid);
            updateList.add(updateDataEntity);
        }
        return updateList;
    }
    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        PayPlanUpdateBatchDTO payPlanUpdateBatchDTO = new PayPlanUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, payPlanUpdateBatchDTO);
        List<PayPlanUpdateDTO> payPlanList = new ArrayList<>();
        addBatchList.forEach(item ->{
            PayPlanUpdateDTO payPlanUpdateDTO = new PayPlanUpdateDTO();
            payPlanUpdateDTO.setData(item.getData());
            payPlanUpdateDTO.setId(item.getId());
            payPlanList.add(payPlanUpdateDTO);
        });
        payPlanUpdateBatchDTO.setPayPlanList(payPlanList);
        updateBatch(payPlanUpdateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        String corpid = saasFormSaveDTO.getCorpid();
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long dataId = newPaasFormDataEntity.getId();
        JSONObject payPlanData = newPaasFormDataEntity.getData();
        Long linkSupplierId = FastJsonHelper.getLongOrDefaultFromFormData(payPlanData, PayPlanEnum.LINK_SUPPLIER.getAttr(),0L);
        Long linkPurchaseId = FastJsonHelper.getLongOrDefaultFromFormData(payPlanData,PayPlanEnum.LINK_PURCHASE.getAttr(),0L);
        userTeamService.createPayPlanUser(corpid,linkSupplierId,linkPurchaseId,Arrays.asList(dataId),false);
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) {

    }
}
